﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using System.ComponentModel;
using HtmlAgilityPack;
using System.Threading.Tasks;
using Windows.Web.Syndication;

namespace Windows_Azure_App.DataModel
{
    public sealed class RSSFeedSourceHelper
    {
        private SyndicationClient _client = new SyndicationClient();
        
        private static string _dashboardPageUrl = "https://www.windowsazurestatus.com/";
        private static string _assetUri = "/Assets/";

        private static RSSFeedSourceHelper _helper = new RSSFeedSourceHelper();
        private HtmlDocument _htmlDoc;
        private List<AzureServiceWebsiteObject> _statusObjectList = new List<AzureServiceWebsiteObject>();

        public RSSFeedSourceHelper()
        {
            _client.BypassCacheOnRetrieve = true;
            _client.SetRequestHeader("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
        }

        /// <summary>
        /// AllRssFeeds returns a List with url's scraped from the Microsoft Windows Azure status dashboard page.
        /// </summary>
        /// <returns>List</returns>
        public static async Task<List<string>> AllRssFeeds()
        {

            List<string> feeds = new List<string>();
            // Load Azure Service Dashboard HTML page
            HtmlDocument doc = await LoadFromWebAsync(_dashboardPageUrl);
            // Select the a href information which are the links to the RSS feeds
            var scrapedUrls = doc.DocumentNode.Descendants("a").Where(d => d.GetAttributeValue("href", "").Contains("RSSFeedCode"));

            foreach (var url in scrapedUrls)
            {
                string feedUrl = _dashboardPageUrl + url.GetAttributeValue("href", "");
                System.Diagnostics.Debug.WriteLine("Feed {0}", feedUrl);
                feeds.Add(feedUrl);
            }
            // remove duplicate entries
            feeds = feeds.Distinct().ToList();
            return feeds;
        }
        
        /// <summary>
        /// Returns a distinct list of all the regions of the Windows Azure dashboard
        /// </summary>
        /// <returns></returns>
        public static async Task<List<string>> GetRegions()
        {
            // Load Azure Service Dashboard HTML page
            HtmlDocument doc = await LoadFromWebAsync(_dashboardPageUrl);
            
            List<string> groups = doc.DocumentNode
                .Descendants("span")
                        .Where(span => span.GetAttributeValue("id", "")
                            .Contains("MainContent_tcStatus_tpAllStatusToday_gvAllStatusToday_lblRegionName_"))
                            .Select(e => e.InnerText)
                            .Distinct()
                            .ToList<string>();
            return groups;
        }

        /// <summary>
        /// Scrape current status from the Windows Azure status website and return the list with found status objects
        /// </summary>
        /// <returns>List statusobjects</returns>
        public static async Task<List<AzureServiceWebsiteObject>> GetScrapedStatusWindowsAzureStatusCom()
        {
            // Load Azure Service Dashboard HTML page
            HtmlDocument doc = await LoadFromWebAsync(_dashboardPageUrl);
            // Select the a href information which are the links to the RSS feeds
            var tableRows = doc.DocumentNode
            .Descendants("tr")
            .Where(tr => tr.ParentNode.Id.Equals("MainContent_tcStatus_tpAllStatusToday_gvAllStatusToday"));
            //.Where(tr => tr.Descendants("td").ToArray().Length > 0);
            foreach (var row in tableRows)
            {
                try
                {
                    string imagePath = _assetUri + row
                        .Descendants("img")
                        .First(img => img.GetAttributeValue("id", "").Contains("MainContent_tcStatus_tpAllStatusToday_gvAllStatusToday_imgStatus_")).GetAttributeValue("src", "");

                    string serviceName = row
                        .Descendants("span")
                        .First(span => span.GetAttributeValue("id", "").Contains("MainContent_tcStatus_tpAllStatusToday_gvAllStatusToday_lblServiceName_"))
                        .InnerText;

                    string regionName = row
                        .Descendants("span")
                        .First(span => span.GetAttributeValue("id", "").Contains("MainContent_tcStatus_tpAllStatusToday_gvAllStatusToday_lblRegionName_"))
                        .InnerText;

                    string statusDetails = row
                        .Descendants("span")
                        .First(span => span.GetAttributeValue("id", "").Contains("MainContent_tcStatus_tpAllStatusToday_gvAllStatusToday_lblDetails_"))
                        .InnerText;

                    string statusFeed = _dashboardPageUrl + row
                        .Descendants("a")
                        .First(span => span.GetAttributeValue("id", "").Contains("MainContent_tcStatus_tpAllStatusToday_gvAllStatusToday_hyperlinkRSS_"))
                        .GetAttributeValue("href", "");

                    if (imagePath != string.Empty && serviceName != string.Empty && regionName != string.Empty && statusDetails != string.Empty && statusFeed != string.Empty) 
                    {
                        AzureServiceWebsiteObject aswso = new AzureServiceWebsiteObject()
                        {
                            Title = serviceName,
                            ImagePath = imagePath,
                            Region = regionName,
                            RSSFeed = statusFeed,
                            Status = statusDetails
                        };
                        _helper._statusObjectList.Add(aswso);
                        System.Diagnostics.Debug.WriteLine("Status object found {0} : {1} : {2} : {3} : {4}", aswso.Title, aswso.Region, aswso.Status, aswso.RSSFeed, aswso.ImagePath);
                    }
                }
                catch
                {
                    // ignore parsing exceptions due to invalid HTML or empty tr nodes
                }
            }
            // remove duplicate entries
            _helper._statusObjectList = _helper._statusObjectList.Distinct().ToList();
            return _helper._statusObjectList;
        }

        /// <summary>
        /// Load a website
        /// </summary>
        /// <returns></returns>
        private static async Task<HtmlDocument> LoadFromWebAsync(string websiteUrl)
        {
            if (_helper._htmlDoc == null)
            {
                try
                {
                    HtmlWeb html = new HtmlWeb();
                    _helper._htmlDoc = await html.LoadFromWebAsync(websiteUrl);
                }
                catch
                {
                    throw;
                }
            }
            return _helper._htmlDoc;
        }

        private static string GetExtensionElementValue(SyndicationItem item, string extensionElementName)
        {
            string status = string.Empty;
            try
            {
                status = item.ElementExtensions.Where(ee => ee.NodeName == extensionElementName).First().NodeValue;
            }
            catch
            {
                status = "Grey";
            }
            return status;
        }

        /// <summary>
        /// Retrieves a Rss Feed 
        /// </summary>
        /// <param name="feedUriString">the URL of the Rss Feed</param>
        /// <returns>SyndicationFeed object or Exception</returns>
        private static async Task<SyndicationFeed> GetFeedAsync(string feedUriString)
        {
            Uri feedUri = new Uri(feedUriString);
            SyndicationFeed feed;
            try
            {
                feed = await _helper._client.RetrieveFeedAsync(feedUri);
            }
            catch
            {
                throw;
            }
            return feed;
        }

        internal static async Task<List<AzureServiceWebsiteObject>> LoadRssFeedInStatusItem(string feedUriString)
        {
            if (feedUriString == string.Empty) throw new InvalidOperationException("Parameter cannot be empty");

            List<AzureServiceWebsiteObject> feedList = new List<AzureServiceWebsiteObject>();
            SyndicationFeed feed = await GetFeedAsync(feedUriString);

            foreach (SyndicationItem syndicationItem in feed.Items)
            {
                string title = syndicationItem.Title.Text;
                string description = syndicationItem.Summary.Text;
                string status = RSSFeedSourceHelper.GetExtensionElementValue(syndicationItem, "status");
                string imageUri = "Assets/windowsazure/support/status/Images/";
                string imagePath = string.Empty;
                switch (status)
                {
                    case "Red":
                        imagePath = imageUri + "red.png";
                        break;
                    case "Yellow":
                        imagePath = imageUri + "yellow2.png";
                        break;
                    case "Green(Info)":
                        imagePath = imageUri + "green_w_info.png";
                        break;
                    case "Resolved":
                        imagePath = imageUri + "green.png";
                        break;
                    default:
                        imagePath = imageUri + "green.png";
                        break;
                }

                DateTime publisehdDate = syndicationItem.PublishedDate.ToLocalTime().LocalDateTime;
                string rftDescription = HTMLtoRTFHelper.HTMLtoRTF(description);

                AzureServiceWebsiteObject item = new AzureServiceWebsiteObject();
                item.Title = title;
                item.Status = status;
                item.PublishedDate = publisehdDate;
                item.ImagePath = imagePath;
                item.RSSFeed = feedUriString;
                item.Description = rftDescription;

                feedList.Add(item);
            }
            return feedList;
        }
    }

    public class AzureServiceWebsiteObject
    {
        public string Title { get; set; }
        public string Region { get; set; }
        public string Status { get; set; }
        public string Description { get; set; }
        public string ImagePath { get; set; }
        public string RSSFeed { get; set; }
        public DateTime PublishedDate { get; set; }
    }
}
